﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Windows.Media.Imaging;
using System.Drawing;
using System.Windows.Media;

namespace Player
{
    public class ExportProgressUpdatedEventArgs : EventArgs
    {
        public ExportProgressUpdatedEventArgs(double progress)
        {
            Progress = progress;
        }

        public double Progress { get; protected set; }
    }

    public class ExportWmvThread : WorkerThread<ExportProgressUpdatedEventArgs>
    {
        private SessionBase m_session;
        private RenderEngine m_engine;

        public ExportWmvThread(SessionBase session)
        {
            m_session = session;
        }

        private BitmapSource ScaleImage(BitmapSource sourceImage, Size scaledSize)
        {
            Size sourceSize = new Size(sourceImage.PixelWidth, sourceImage.PixelHeight);

            // If this is an unscaled image... we do nothing!
            if (scaledSize == Size.Empty ||
                scaledSize == sourceSize)
            {
                return sourceImage;
            }

            // Otherwise, scale, maintaining aspect ratio
            float percW = (scaledSize.Width / (float)sourceSize.Width);
            float percH = (scaledSize.Height / (float)sourceSize.Height);
            float percX = Math.Min(percW, percH);
            float percY = percX;

            return new TransformedBitmap(sourceImage, new ScaleTransform(percX, percY));
        }

        private BitmapSource FlipImage(BitmapSource sourceImage)
        {
            return new TransformedBitmap(sourceImage, new ScaleTransform(1, -1));
        }

        private BitmapSource PadImage(BitmapSource sourceImage, Size paddedSize)
        {
            // Create a writeable image the appropriate size, same format/palette as original            
            WriteableBitmap wbmp = new WriteableBitmap(paddedSize.Width, paddedSize.Height, 96.0f, 96.0f, sourceImage.Format, sourceImage.Palette);

            // Work out starting X/Y for our write, so that our padding surrounds the original (centers)
            int startX = (paddedSize.Width / 2) - (sourceImage.PixelWidth / 2);
            int startY = (paddedSize.Height / 2) - (sourceImage.PixelHeight / 2);

            // Pull pixel data from our source (tbd: faster way to draw this instead of copies?)
            int stride = (sourceImage.PixelWidth * (sourceImage.Format.BitsPerPixel / 8));

            using (CachedBuffer cb = CachedBufferAllocator.GetCachedBuffer(sourceImage.PixelHeight * stride))
            {
                sourceImage.CopyPixels((byte[])cb, stride, 0);

                // Write pixel data to our new (correct size) image
                wbmp.WritePixels(new System.Windows.Int32Rect(startX, startY, sourceImage.PixelWidth, sourceImage.PixelHeight), (byte[])cb, stride, 0);
            }
            return (BitmapSource)wbmp;
        }

        protected override void Run(params object[] args)
        {
            //Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;
            //m_engine = m_session.CreateRenderEngine();

            //string filename = (string)args[0];
            //long startTime = 0;
            //int bitrate = 512 * 1000;   // 512kbps
            //float fps = 10.0f;          // 10 frames/sec                

            //WmvFile wmvFile = new WmvFile(filename, fps, bitrate);

            //try
            //{
            //    Size movieSize = Size.Empty;
            //    bool firstFrame = true;
            //    foreach (Frame frame in m_session.LoadFrames(0))
            //    {
            //        // Every frame, check for whether we've been stopped...
            //        if (ShouldStop) break;

            //        m_engine.Process(frame);

            //        double progress = m_session.GetElapsedTime(frame.TimeStamp).TotalMilliseconds / m_session.Length;
            //        Log.Trace("Progress: {0}", progress);
            //        Update(new ExportProgressUpdatedEventArgs(progress));

            //        // First frame, now we know size, start movie creation
            //        if (firstFrame)
            //        {
            //            movieSize = new Size(m_engine.Image.PixelWidth, m_engine.Image.PixelHeight);
            //            wmvFile.BeginMovieCreation(movieSize.Width, movieSize.Height, 32);
            //            startTime = frame.TimeStamp;
            //            firstFrame = false;
            //        }

            //        // Scale our image if needed, maintains aspect ratio
            //        BitmapSource outputImage = ScaleImage(m_engine.Image, movieSize);

            //        // If scaled, pad the image so that it is the appropriate output size                    
            //        if (outputImage.PixelHeight != movieSize.Height || outputImage.PixelWidth != movieSize.Width)
            //        {
            //            outputImage = PadImage(outputImage, movieSize);
            //        }

            //        // Flip Y
            //        outputImage = FlipImage(outputImage);

            //        // Write it out
            //        wmvFile.AddFrame(outputImage, frame.TimeStamp - startTime);
            //    }
            //}
            //finally
            //{
            //    if (startTime != 0)
            //        wmvFile.FinishMovieCreation();
            //}
        }
    }
}
